<?php

namespace App\Logic;

use App\Model\Menu;
use Exception;

class AdminMenuLogic
{
    const int MAX_MENU_LEVEL = 5;

    /**
     * 获取菜单列表
     * @param $treeMode
     * @return array
     */
    public static function lists($treeMode = false): array
    {
        $menus = Menu::query()->orderBy('listorder')->get()->keyBy('id')->toArray();
        if ($treeMode) {
            $menus = self::_getMenuTree($menus);
        }
        return $menus;
    }

    /**
     * 添加菜单
     * @param $input
     * @return true
     * @throws Exception
     */
    public static function add($input): true
    {
        $menu = Menu::create([
            'name' => $input['name'],
            'parentid' => $input['parentId'],
            'is_show' => $input['isShow'],
            'is_quick' => $input['isQuick'],
            'url' => $input['url'],
            'style' => $input['style'],
            'type' => $input['type'],
            'listorder' => $input['listorder'],
        ]);
        if (!$menu) {
            throw new Exception('添加失败');
        }
        if ($menu['parentid'] > 0) {
            Menu::query()->where('id', $menu['parentid'])->update(['child' => 1]);
        }
        return true;
    }

    /**
     * 修改菜单
     * @throws Exception
     */
    public static function edit($id, $input): true
    {
        $menu = Menu::query()->where('id', $id)->first();
        if (!$menu) {
            throw new Exception('菜单不存在');
        }
        if (!in_array($id, self::_getAllChildIds($id))) {
            throw new Exception('上级分类选择异常');
        }
        $ret = Menu::query()->where('id', $id)->update([
            'name' => $input['name'],
            'parentid' => $input['parentId'],
            'is_show' => $input['isShow'],
            'is_quick' => $input['isQuick'],
            'url' => $input['url'],
            'style' => $input['style'],
            'type' => $input['type'],
            'listorder' => $input['listorder']
        ]);
        $isChild = Menu::query()->where('parentid', $menu['parentid'])->exists() ? 1 : 0;
        Menu::query()->where('id', $menu['parentid'])->update(['child' => $isChild]);
        return true;
    }

    /**
     * 删除菜单
     * @param $menuId
     * @return true
     * @throws Exception
     */
    public static function delete($menuId): true
    {
        $allChildIds = self::_getAllChildIds($menuId);
        if (count($allChildIds) > 1) {
            throw new Exception('该菜单包含子菜单，不可删除');
        }
        Menu::query()->where('id', $menuId)->delete();
        return true;
    }

    /**
     * 获取菜单详情
     * @param $menuId
     * @return array
     */
    public static function detail($menuId): array
    {
        return Menu::query()->where('id', $menuId)->first()->toArray();
    }

    /**
     * 修改参数
     * @param $id
     * @param $field
     * @param $value
     * @return true
     * @throws Exception
     */
    public static function updateField($id, $field, $value): true
    {
        if (!in_array($field, ['listorder', 'url'])) {
            throw new Exception('该参数不允许修改');
        }
        Menu::query()->where('id', $id)->update([$field => $value]);
        return true;
    }

    /**
     * 获取树形菜单
     * @param $menu
     * @param $parent_id
     * @param $level
     * @return array
     */
    private static function _getMenuTree($menu, $parent_id = 0, $level = 1): array
    {
        $data = [];
        if ($level <= self::MAX_MENU_LEVEL) {
            foreach ($menu as $id => $m) {
                if ($m['parentid'] == $parent_id && $m['type'] == 1) {
                    $child = $m['child'] ? self::_getMenuTree($menu, $id, $level + 1) : [];
                    $_menu = [
                        'title' => $m['name'],
                        'href' => $m['url'],
                        'icon' => 'fa ' . $m['style'],
                        'target' => '_self',
                    ];
                    if (!empty($child)) {
                        $_menu['child'] = $child;
                    }
                    $data[] = $_menu;
                }
            }
        }
        return $data;
    }

    /**
     * 获取全部子菜单ID
     * @param $id
     * @param $childIds
     * @return array|mixed
     */
    private static function _getAllChildIds($id, $childIds = []): mixed
    {
        $childIds[] = $id;
        $ids = Menu::query()->where('parentid', $id)->get(['id'])->pluck('id');
        foreach ($ids as $_id) {
            $childIds = self::_getAllChildIds($_id, $childIds);
        }
        return $childIds;
    }
}